import {
  BleUtils
} from "./BleUtils";
import {
  DscpProtocol
} from '../protocol/dscp/DscpProtocol';
let dscpProtocol = new DscpProtocol();
var DscpCode = require('../protocol/dscp/DscpCode');
import {
  ByteUtils
} from './ByteUtils';
let byteUtils = new ByteUtils();
let bleTaskMap = new Map();

class BleDscpUtils extends BleUtils {

  operateKey = null;

  constructor() {
    if (!BleDscpUtils.instance) {
      super();
      BleDscpUtils.instance = this;
      console.log("---BleDscpUtils实例化---")
    }
    return BleDscpUtils.instance;
  }

  setOperateKey(operateKey) {
    this.operateKey = operateKey;
  }

  /**
   * 设置设备的注册状态
   * 用于在连接过程设备注册状态的改变
   */
  setDeviceRegisterStatus(isRegisted, operateKey) {
    this.manufacturerData.isRegister = isRegisted;
    if (isRegisted) {
      this.operateKey = operateKey;
      dscpProtocol.setDeviceAesKey(byteUtils.uuidToBytes(operateKey));
    } else {
      dscpProtocol.setDeviceAesKey(null);
    }
  }

  sendCmdTest(callback, sendCmd, sendCmdData) {
    let key = this.operateKey;
    this.sendCmd(callback, sendCmd, sendCmdData, key)
  }

  /**
   * 发送命令到设备
   * @param {回调函数} callback 
   * @param {发送的命令码} sendCmd 
   * @param {发送的命令参数} sendCmdData 
   * @param {该设备的操作密钥} operateKey 
   */
  sendCmd(callback, sendCmd, sendCmdData, operateKey) {
    if (!this.isConnected) {
      callback(false, null)
      my.showToast({
        content: '请先连接蓝牙',
        icon: 'none',
      });
      return;
    }
    // let isNotNeedEncrypt = false;
    // if (this.manufacturerData.isRegister) {
    //   // 设备已注册
    //   if (!operateKey) {
    //     console.log("没有该设备的密钥")
    //     my.showToast({
    //       title: '没有该设备的密钥，无法对该设备进行操作',
    //       icon: 'none',
    //     });
    //     return;
    //   } else {
    //     // 第一条命令需要是设置会话码
    //     if (!this.curSessionCode) {
    //       if (sendCmd != DscpCode.SET_SESSION_CODE) {
    //         console.log("------请先设置会话码-未注册------");
    //         dscpProtocol.setDeviceAesKey(null);
    //         my.showToast({
    //           icon: 'none',
    //           title: '请先设置会话码'
    //         })
    //         return;
    //       } else {
    //         isNotNeedEncrypt = true;
    //       }
    //     }
    //   }
    // } else {
    //   // 设备未注册
    //   // 第一条命令需要是设置会话码
    //   if (!this.curSessionCode) {
    //     if (sendCmd != DscpCode.SET_SESSION_CODE) {
    //       console.log("------请先设置会话码-未注册------");
    //       dscpProtocol.setDeviceAesKey(null);
    //       my.showToast({
    //         icon: 'none',
    //         title: '请先设置会话码'
    //       })
    //       return;
    //     } else {
    //       isNotNeedEncrypt = true;
    //     }
    //   }
    // }
    // // 设置会话码指令都不进行加密
    // if (sendCmd == DscpCode.SET_SESSION_CODE) {
    //   isNotNeedEncrypt = true;
    // }
    let sendData = dscpProtocol.packetToBytes(sendCmd, sendCmdData, false);
    if (this.isConnectHandAlready) {
      this._realSendCmd(callback, sendCmd, sendData, null)
    } else {
      console.log("BleDscpUtils---开始握手---")
      this.connectHand((result, obj) => {
        if (obj) {
          if (obj.isSucceed) {
            console.log("------握手成功------")
            this.isConnectHandAlready = true
            this._realSendCmd(callback, sendCmd, sendData, null)
          } else {
            callback(false)
            this.isConnectHandAlready = false
            console.log("------握手失败------", obj)
          }
        } else {
          callback(false)
          this.isConnectHandAlready = false
          console.log("------握手失败------超时")
        }
      })
    }

  }

  /**
* 连接握手
* 0x5C,0x5F,0x57,0x59,0x5E （固定）
*/
  connectHand(callback) {
    let sendCmdData = Array()
    sendCmdData.push(0x5C)
    sendCmdData.push(0x5F)
    sendCmdData.push(0x57)
    sendCmdData.push(0x59)
    sendCmdData.push(0x5E)
    let sendData = dscpProtocol.packetToBytes(DscpCode.CONNECT_HAND, sendCmdData, false);
    this._realSendCmd((result, recvCmdData) => {
      if (!result) {
        callback(false)
        return;
      }
      console.log("收到握手回复")
      let obj = new Object();
      obj.isSucceed = recvCmdData[0] == 2 ? true : false; // true设置成功
      obj.errCode = recvCmdData[0] == 0 ? 0xFF : recvCmdData[0];
      callback(true, obj);
    }, DscpCode.CONNECT_HAND, sendData);
  }

  /**
   * 真正发送数据
   * @param {回调函数} callback 
   * @param {发送的命令码} sendCmd 
   * @param {该设备的操作密钥} operateKey 
   */
  _realSendCmd(callback, sendCmd, sendData, operateKey) {
    console.log("真的开始发送数据了--")
    this.addTimeoutTask(callback, sendCmd);
    this.sendDataToBle(sendData, sendCmd, (succeed, recvData) => {
      if (succeed) {
        dscpProtocol.parse(recvData, (recvCmd, recvCmdData) => {
          if (recvCmd == DscpCode.SET_SESSION_CODE) {
            console.log("------设置密钥中------")
            if (recvCmdData[0] == 0) {
              // 设置密钥成功
              let userId = byteUtils.bytes2ToInt(recvCmdData.slice(2, 6));
              let sessionCode = recvCmdData.slice(6, 14);
              if (this.manufacturerData.isRegister || userId != 0xffff) {
                dscpProtocol.setDeviceAesKey(getNewDeviceAesKey(byteUtils.uuidToBytes(operateKey), sessionCode))
              } else {
                dscpProtocol.setDeviceAesKey(sessionCode.concat(sessionCode))
              }
              this.curSessionCode = sessionCode;
              this.setMTU(recvCmdData[15]);
            } else {
            }
          }
          for (let [call, aSendCmd] of bleTaskMap.entries()) {
            console.log("aSendCmd = ", aSendCmd, " recvCmd = ", recvCmd)
            if (aSendCmd == recvCmd) {
              call(true, recvCmdData);
              bleTaskMap.delete(call);
              break;
            }
          }
        })
      } else {
        console.log("发送失败--底层发送数据失败")
        for (let [call, aSendCmd] of bleTaskMap.entries()) {
          if (aSendCmd == recvData) {
            console.error("没有找到有效的sendCmd");
            console.error("aSendCmd = ", aSendCmd, "recvCmd = ", recvData);
            call(false);
            bleTaskMap.delete(call);
          }
        }
      }
    })
  }

  // 蓝牙发送任务2.5s超时
  addTimeoutTask(callback, sendCmd) {
    console.log("---添加了蓝牙超时任务---")
    bleTaskMap.set(callback, sendCmd);
    setTimeout(() => {
      if (bleTaskMap.has(callback)) {
        console.warn("---蓝牙超时任务执行---")
        callback(false)
        bleTaskMap.delete(callback);
      }
    }, 2500);
  }
}

/**
   * 根据操作密钥和会话码生成AES密钥
   * @param {操作密钥} operateKey 
   * @param {会话码} sessionCode 
   */
function getNewDeviceAesKey(operateKey, sessionCode) {
  console.log("--------操作密钥和会话码组合--------")
  console.log("operateKey = " + byteUtils.ab2hex(operateKey))
  console.log("sessionCode = " + byteUtils.ab2hex(sessionCode))
  for (let i = 0; i < sessionCode.length; ++i) {
    operateKey[i] = (operateKey[i] & sessionCode[i])
  }
  console.log("result = " + byteUtils.ab2hex(operateKey))
  return operateKey;
}

export {
  BleDscpUtils
}